﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Xml;
using System.Xml.Serialization;

namespace VswService_V7.Utility
{
    /// <summary>
    /// Operations on XML files (addition, deletion and modification)
    /// </summary>
    public class XmlHelper
    {
        /// <summary>
        /// read data
        /// </summary>
        /// <param name="path">path</param>
        /// <param name="node">node</param>
        /// <param name="attribute">Attribute name, return the attribute value if it is not empty, otherwise return the concatenated value</param>
        /// <returns>string</returns>
        /**************************************************
         * Use display:
         * XmlHelper.Read(path, "/Node", "")
         * XmlHelper.Read(path, "/Node/Element[@Attribute='Name']", "Attribute")
         ************************************************/
        public string Read(string path, string nodename, string attribute)
        {
            string value = "";
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(path);
                XmlNode node = doc.SelectSingleNode(nodename);
                value = node.SelectSingleNode(attribute).InnerText;
            }
            catch
            {
                value = "Find failed";
            }
            return value;
        }

        /// <summary>
        /// insert data
        /// </summary>
        /// <param name="path">path</param>
        /// <param name="node">node</param>
        /// <param name="element">Element name, insert a new element when not empty, otherwise insert an attribute in the element</param>
        /// <param name="attribute">Attribute name, insert the element attribute value when it is not empty, otherwise insert the element value</param>
        /// <param name="value">value</param>
        /// <returns></returns>
        /**************************************************
         * Use display:
         * XmlHelper.Insert(path, "/Node", "Element", "", "Value")
         * XmlHelper.Insert(path, "/Node", "Element", "Attribute", "Value")
         * XmlHelper.Insert(path, "/Node", "", "Attribute", "Value")
         ************************************************/
        public void Insert(string path, string nodename, string attribute, string value)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(path);
                XmlNode node = doc.SelectSingleNode(nodename);
                XmlNode newnode = doc.CreateNode(XmlNodeType.Element, attribute, null);
                newnode.InnerText = value;
                node.AppendChild(newnode);

                doc.Save(path);
            }
            catch { }
        }

        /// <summary>
        /// update data
        /// </summary>
        /// <param name="path">path</param>
        /// <param name="node">node</param>
        /// <param name="attribute">Attribute name, modify the node attribute value when it is not empty, otherwise modify the node value</param>
        /// <param name="value">value</param>
        /// <returns></returns>
        /**************************************************
         * use display:
         * XmlHelper.Insert(path, "/Node", "", "Value")
         * XmlHelper.Insert(path, "/Node", "Attribute", "Value")
         ************************************************/
        public void Update(string path, string nodename, string attribute, string value)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(path);
                XmlNode node = doc.SelectSingleNode(nodename);
                node.SelectSingleNode(attribute).InnerText = value;
                doc.Save(path);
            }
            catch
            {

            }

        }

        /// <summary>
        /// dalete data
        /// </summary>
        /// <param name="path">path</param>
        /// <param name="node">node</param>
        /// <param name="attribute">Attribute name, delete the node attribute value if it is not empty, otherwise delete the node value</param>
        /// <param name="value">value</param>
        /// <returns></returns>
        /**************************************************
         * Use display:
         * XmlHelper.Delete(path, "/Node", "")
         * XmlHelper.Delete(path, "/Node", "Attribute")
         ************************************************/
        public void Delete(string path, string nodename, string attribute)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(path);
                XmlNode node = doc.SelectSingleNode(nodename);
                node.RemoveChild(node.SelectSingleNode(attribute));
                doc.Save(path);
            }
            catch
            {

            }
        }


        /// <summary>
        /// Save a T class as an XML file
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="path"></param>
        public static void Save<T>(T t, string path)
        {

            FileStream stream = File.Create(path);
            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                serializer.Serialize(stream, t);
            }
            catch (Exception ex)
            {
                stream.Close();
                throw ex;
            }
            stream.Close();
        }

        /// <summary>
        /// Load an XML file into the T class
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path"></param>
        /// <returns></returns>
        public static T Load<T>(string path)
        {
            FileStream stream = File.OpenRead(path);
            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                T t = (T)serializer.Deserialize(stream);
                stream.Close();
                return t;
            }
            catch (Exception ex)
            {
                stream.Close();
                throw ex;
                //return default(T);
            }

        }

        //Read XML file attributes
        public static string ReadAttribute(string xmlPath, string attribute)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlPath);
            XmlNode xmlNode = xmlDoc.SelectSingleNode(attribute);
            string value = xmlNode.InnerText;
            return value;
        }

        //Modify XML file attribute values
        public static void ChangeAttribute(string xmlPath, string attribute, string value)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlPath);
            XmlNode xmlNode = xmlDoc.SelectSingleNode(attribute);
            xmlNode.InnerText = value;
            xmlDoc.Save(xmlPath);
        }



    }
}
